package com.qzct.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrPool;
import com.qzct.config.MinioProperties;
import com.qzct.entity.vo.ResultCode;
import com.qzct.exceptions.ApiException;
import com.qzct.service.FileService;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;

@Service
public class FileServiceImpl implements FileService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private MinioClient minioClient;
    @Resource
    private MinioProperties minioProperties;

    /**
     * 格式化时间
     */
    private static final String DATE_FORMAT = "yyyyMMdd";

    /**
     * 字符集
     */
    private static final String ENCODING = "UTF-8";
    @Override
    public boolean bucketExists(String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build());
        } catch (Exception e) {
            logger.error("minio bucketExists Exception:{}", e);
        }
        return false;
    }

    @Override
    public String upLoadImg(String folderName, String fileName, MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new ApiException(ResultCode.CUSTOM_ERROR,"图片不能为空");
        }
        // 文件大小
        if (file.getSize() > 20 * 1024 * 1024) {
            throw new ApiException(ResultCode.CUSTOM_ERROR,"图片大小不能大于20M");
        }
        String suffix = FileUtil.getSuffix(file.getOriginalFilename());
        // 文件后缀判断
        if (!CollUtil.contains(minioProperties.getImgExt(), suffix)) {
            String error = String.format("图片类型错误,目前支持[%s]等文件类型",
                    String.join(",", minioProperties.getImgExt()));
//
            throw new ApiException(ResultCode.CUSTOM_ERROR,error);
        }
        try {
            return upLoadFile(minioProperties.getBucketName(),folderName, fileName, suffix,file.getSize(),file.hashCode(), file.getInputStream(),file.getContentType());
        } catch (Exception e) {
            logger.error("minio upLoadFile Exception:{}", e);
            throw new ApiException(ResultCode.CUSTOM_ERROR,e.getMessage());
        }
    }
    @SneakyThrows
    public String upLoadFile(String bucketName, String folderName, String fileName, String suffix, long size, int hash, InputStream stream,
                             String contentType) {
        if (!bucketExists(bucketName)) {
            logger.info("minio bucketName is not creat");
            makeBucket(bucketName);
        }
        String filePath = getFilePath(folderName, fileName, suffix);
        minioClient.putObject(PutObjectArgs.builder().bucket(getBucketName(bucketName)).object(filePath)
                .stream(stream, stream.available(), -1).contentType(contentType).build());
        String url = getOssHost(bucketName)+filePath;
        stream.close();
        logger.info("minio upLoadFile success, filePath:{}", filePath);
        return url;
    }

    //    公共需要的部分
    public void makeBucket(String bucketName) {
        try {
            if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build())) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(getBucketName(bucketName)).build());
                logger.info("minio makeBucket success bucketName:{}", bucketName);
            }
        } catch (Exception e) {
            logger.error("minio makeBucket Exception:{}", e);
        }
    }
    private String getBucketName(String bucketName) {
        return bucketName;
    }
    private String getFilePath(String folderName, String originalFilename, String suffix) {
        return StrPool.SLASH + String.join(StrPool.SLASH, folderName, DateUtil.date().toString(DATE_FORMAT),
                originalFilename) + StrPool.C_UNDERLINE + DateUtil.current() + StrPool.DOT + suffix;
    }
    public String getOssHost(String bucketName) {
        return minioProperties.getEndpoint()+ StrPool.SLASH + getBucketName(bucketName);
    }
}
